package com;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.converts.OracleTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

/**
 * <p>
 * 代码生成器演示
 * </p>
 *
 * @author lichengduo
 * @date 2017-12-01
 */
public class OracleGenerator {

	private static final String SQL_DRIVER_TYPE_ORACLE_SQL = "oracle.jdbc.driver.OracleDriver";
	private static final String TEMPLATES = "/templates/";

	/**
	 * <p>
	 * Oracle 生成演示
	 * </p>
	 */
	public String gen(Map<String, Object> dataMap) {

		String urlPath = ObjectParser.toString(dataMap.get("urlPath"));
		String filePath = ObjectParser.toString(dataMap.get("filePath"));
		final String table = ObjectParser.toString(dataMap.get("table"));
		String author = ObjectParser.toString(dataMap.get("author"));

		String username = ObjectParser.toString(dataMap.get("username"));
		String password = ObjectParser.toString(dataMap.get("password"));
		String url = ObjectParser.toString(dataMap.get("url"));

		final String packageName = ObjectParser
				.toString(StringUtils.isEmpty(dataMap.get("packageName")) ? "com" : dataMap.get("packageName"));
		if (StringUtils.isEmpty(author)) {
			author = "lichengdu";
		}
		// 拼接模块名去掉下划线
		final String moduleName = table.toLowerCase().replaceAll("_", "");

		String zipName =  table.toLowerCase() + "-gen.zip";
		// 本地路径
		String zipPath = filePath + File.separator +  table.toLowerCase();
		String outPutDir = zipPath;
		String zipedPath = filePath + File.separator + zipName;
		// 下载路径
		String zipDownloadPath = urlPath + zipName;

		// 代码生成器
		AutoGenerator mpg = new AutoGenerator();

		// 全局配置
		GlobalConfig gc = new GlobalConfig();
		gc.setOutputDir(outPutDir);
		gc.setFileOverride(true);
		gc.setActiveRecord(true);
		gc.setEnableCache(false);// XML 二级缓存
		gc.setBaseResultMap(true);// XML ResultMap
		gc.setBaseColumnList(false);// XML columList
		gc.setAuthor(author);
		gc.setOpen(false);
		gc.setMapperName("%sDao");
		gc.setXmlName("%sDao");
		gc.setServiceImplName("%sImplDao");
		mpg.setGlobalConfig(gc);

		// 数据源配置
		DataSourceConfig dsc = new DataSourceConfig();
		dsc.setDbType(DbType.ORACLE);
		dsc.setTypeConvert(new OracleTypeConvert(){
            // 自定义数据库表字段类型转换【可选】
            @Override
            public DbColumnType processTypeConvert(String fieldType) {
                System.out.println("转换类型：" + fieldType);
        // 注意！！processTypeConvert 存在默认类型转换，如果不是你要的效果请自定义返回、非如下直接返回。
                return super.processTypeConvert(fieldType);
            }
        });
		
		dsc.setDriverName(SQL_DRIVER_TYPE_ORACLE_SQL);
		dsc.setUsername(username);
		dsc.setPassword(password);
		dsc.setUrl(url);
		mpg.setDataSource(dsc);

		// 策略配置
		StrategyConfig strategy = new StrategyConfig();
		// strategy.setCapitalMode(true);// 全局大写命名 ORACLE 注意
		strategy.setTablePrefix(new String[] { "CRM_", "tsys_" });// 此处可以修改为您的表前缀
		strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
		strategy.setInclude(new String[] { table }); // 需要生成的表
		// strategy.setExclude(new String[]{"test"}); // 排除生成的表
		// 自定义实体父类
		// strategy.setSuperEntityClass("com.baomidou.demo.TestEntity");
		// 自定义实体，公共字段
		// strategy.setSuperEntityColumns(new String[] { "test_id", "age" });
		// 自定义 mapper 父类
		// strategy.setSuperMapperClass("com.baomidou.demo.TestMapper");
		// 自定义 service 父类
		// strategy.setSuperServiceClass("com.baomidou.demo.TestService");
		// 自定义 service 实现类父类
		// strategy.setSuperServiceImplClass("com.baomidou.demo.TestServiceImpl");
		// 自定义 controller 父类
		// strategy.setSuperControllerClass("com.baomidou.demo.TestController");
		// 【实体】是否生成字段常量（默认 false）
		// public static final String ID = "test_id";
		// strategy.setEntityColumnConstant(true);
		// 【实体】是否为构建者模型（默认 false）
		// public User setName(String name) {this.name = name; return this;}
		// strategy.setEntityBuliderModel(true);
		mpg.setStrategy(strategy);

		// 包配置
		PackageConfig pc = new PackageConfig();
		pc.setModuleName(moduleName);
		pc.setParent(packageName);// 自定义包路径
		pc.setController("controller");// 这里是控制器包名，默认 web
		pc.setMapper("dao");
		pc.setXml("dao");
		pc.setServiceImpl("impl");
		mpg.setPackageInfo(pc);
		
		// 设置自定义参数
		// 注入自定义配置，可以在 VM 中使用 cfg.abc 设置的值
		InjectionConfig cfg = new InjectionConfig() {
			@Override
			public void initMap() {
				Map<String, Object> map = new HashMap<>();
				map.put("dao_package", packageName + "." + moduleName + ".dao");
				map.put("mapper_namespace", packageName + "." + moduleName + ".dao." + StringUtil.toUpper(table.toLowerCase(), "_")+"Dao");
				map.put("impl_package", packageName + "." + moduleName + ".impl");
				this.setMap(map);
			}
		};
		mpg.setCfg(cfg);

		// 自定义模板配置，模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy
		// 至您项目 src/main/resources/template 目录下，模板名称也可自定义如下配置：
		TemplateConfig tc = new TemplateConfig();
		tc.setMapper(TEMPLATES + "mapper.java");
		tc.setServiceImpl(TEMPLATES + "serviceImpl.java");
		tc.setXml(TEMPLATES + "mapper.xml");
		// 不生成Controller
		tc.setController(null);
		// 不生成Entity
		tc.setEntity(null);
		// Service
		tc.setService(null);
		mpg.setTemplate(tc);
		try {
			// 执行生成
			mpg.execute();
			// 打印注入设置，这里演示模板里面怎么获取注入内容【可无】
			System.out.println("dao_package======" + mpg.getCfg().getMap().get("dao_package"));
			// 打包ZIP zipPath 打包前路径 打包后的路径
			ZipUtils.createZip(zipPath, zipedPath);
			// FileUtils.deleteDirectory(new File("F://GeneratorCode"));
			// 返回下载路径
			return zipDownloadPath;
		} catch (Exception e) {
			throw e;
		}
	}

}
